home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / tutor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-27  |  25.8 KB  |  1,047 lines

  1. #ifndef STANDALONE
  2. #include <stdio.h>
  3. #include <dir.h>
  4. #include <dos.h>
  5. #include <string.h>
  6. #include <time.h>
  7. #include "config.h"
  8. #include "global.h"
  9. #include "files.h"
  10. #include "mailbox.h"
  11. #include "socket.h"
  12. #include "ftp.h"
  13. #include "ax25.h"
  14. #include "session.h"
  15. #include "dirutil.h"
  16. #include "cmdparse.h"
  17. #include "usock.h"
  18. #include "pktdrvr.h"
  19. #endif
  20.  
  21. #ifdef TUTOR
  22. static struct world    {
  23.     int mode;
  24.     char color;
  25.     char colorblock;
  26.     char last[2];
  27.     char inescape;
  28.     char ipconnect;
  29.     char *subdir;
  30.     char *call;
  31. #ifndef STANDALONE
  32.     struct mbx *m;
  33. #endif
  34.     FILE *fp;
  35.     char *Tutors[100];
  36.     int maxselect;
  37.     char *variables[10];
  38.     int indexes[10];
  39.     int socket[10];
  40.     int user;
  41.     int whichsocket;
  42.     int background;
  43.     char Error[80];
  44. };
  45.  
  46. #ifndef STANDALONE
  47. int Tutored = 0;
  48. extern int Stutor, Sinfo, Snews, Tutorlogins[];
  49. extern char Tcall[AXALEN], Icall[AXALEN], Ncall[AXALEN];
  50. extern int rdaemon __ARGS((FILE *data,char *from, char *to, char *msg, char msgtype, int mode));
  51. #endif
  52. #endif
  53.  
  54.  
  55. static void
  56. mycolorchange (here, input, last)
  57. struct world *here;
  58. char *input, *last;
  59. {
  60.     if (here->color)
  61.         colorchange (input, last);
  62. }
  63.  
  64.  
  65. static void
  66. mytprintf (here, str)
  67. struct world *here;
  68. unsigned char *str;
  69. {
  70.     if (here->background && !here->whichsocket)
  71.         return;
  72.     if (!here->colorblock)
  73.         tprintf (str);
  74.     else
  75.         if (colorprintf (&here->inescape, here->color, str))
  76.             here->last[0] = 0;
  77. }
  78.  
  79.  
  80. char *
  81. skipwhite (cp)
  82. char *cp;
  83. {
  84.     while (*cp && (*cp == ' ' || *cp == '\t'))
  85.         cp++;
  86.     return (cp);
  87. }
  88.  
  89.  
  90. char *
  91. skipnonwhite (cp)
  92. char *cp;
  93. {
  94.     while (*cp && *cp != ' ' && *cp != '\t')
  95.         cp++;
  96.     return (cp);
  97. }
  98.  
  99.  
  100. #ifdef TUTOR
  101. #ifndef STANDALONE
  102. static void
  103. mygets (buf, size, here)
  104. char *buf;
  105. int size;
  106. struct world *here;
  107. {
  108.     
  109.     if ((here->background && !here->whichsocket) || here->user < 0)    {
  110.         buf[0] = 0;
  111.         return;
  112.     }
  113.     usflush(Curproc->output);
  114. #ifdef MBXTDISC
  115.     /* Restart the inactivity timer */
  116.     if (here->m != NULLMBX)
  117.         start_timer(&here->m->tdisc);
  118. #endif
  119.     if((size = recvline (here->user ? here->user : Curproc->input, buf, size)) <= 0)    {
  120.         if (here->user > 0)    {
  121.             here->socket[here->whichsocket] = here->user == -1;
  122.             Curproc->output = here->socket[0];
  123.         }
  124.         buf[0] = 0;
  125.     }
  126.     rip (buf);
  127. }
  128. #else
  129. void mygets (char *buf, int size, struct world *here);
  130. #endif
  131.  
  132.  
  133. static char *
  134. nextarg (cp, i)
  135. char *cp;
  136. int *i;
  137. {
  138.     cp = skipnonwhite(cp);
  139.     cp = skipwhite (cp);
  140.     *i = atoi (cp);
  141.     return (cp);
  142. }
  143.  
  144.  
  145. static char *
  146. nextnum (cp, defval, here, i)
  147. char *cp;
  148. int defval, *i;
  149. struct world *here;
  150. {
  151.     cp = skipnonwhite(cp);
  152.     cp = skipwhite (cp);
  153.     *i = getnum (cp, defval, here);
  154.     return (cp);
  155. }
  156.  
  157.  
  158. static int
  159. getnum (cp, defval, here)
  160. char *cp;
  161. int defval;
  162. struct world *here;
  163. {
  164. int l = defval;
  165.  
  166.     switch (*cp)    {
  167.         case '~':    if (tolower (cp[1]) == 'i')    {
  168.                     l = here->indexes[cp[2] - '0'];
  169.                     break;
  170.                 }
  171.                 if (cp[1] >= '0' && cp[1] <= '9')    {
  172.                     l = atoi (here->variables[cp[1] - '0']);
  173.                     break;
  174.                 }
  175.         case 0:        break;
  176.         default:    l = atoi (cp);
  177.                 break;
  178.     }
  179.     return l;
  180. }
  181.  
  182.  
  183. static char SCONFail[] = "SCRIPT connect failed: ";
  184. static char SCONFail2[] = "SCRIPT disconnect failed: ";
  185.  
  186.  
  187. /* open a network connection based upon information in the cc line.
  188.  * m->user is set to the socket number.
  189.  */
  190. static int
  191. scriptconn(argc,argv,p)
  192. int argc;
  193. char *argv[];
  194. void *p;
  195. {
  196. struct world *here;
  197. char sock[MAXSOCKSIZE];
  198. union sp sp;
  199. char ctype;
  200. struct iface *ifp;
  201. char digis[MAXDIGIS][AXALEN];
  202. char target[AXALEN];
  203. int ndigis, i, len;
  204.  
  205.     here = (struct world *)p;
  206.     sp.p = sock;
  207.     here->Error[0] = 0;    /* null error string */
  208.     ctype = tolower(*argv[0]);
  209.     if (argc < 2)    {
  210.         sprintf (here->Error, "%sSyntax Error", SCONFail);
  211.         return -1;
  212.     }
  213.  
  214.     switch (ctype)    {
  215. #ifdef AX25
  216.         case 'a':
  217.         case 'c':    /* allow 'c' for 'connect' as well */
  218.             if( ((ifp = if_lookup(argv[1])) == NULLIF) || (ifp->flags & HIDE_PORT)) {
  219.             sprintf(here->Error, "%sUnknown port %s",SCONFail, argv[1]);
  220.                 return -1;
  221.             }
  222.             if(ifp->type != CL_AX25){
  223.                 sprintf(here->Error, "%sPort %s not usable for AX.25 connects",SCONFail, argv[1]);
  224.                 return -1;
  225.             }
  226.             if(setcall(target,argv[2]) == -1){
  227.                 sprintf(here->Error, "%sBad call %s",SCONFail, argv[2]);
  228.                 return -1;
  229.             }
  230.  
  231.             /* If digipeaters are given, put them in the routing table */
  232.             if(argc > 3)    {
  233.                 ndigis = argc - 3;
  234.                 if(ndigis > MAXDIGIS)    {
  235.                     sprintf (here->Error, "%sToo many digipeaters", SCONFail);
  236.                     return -1;
  237.                 }
  238.                 for(i=0;i<ndigis;i++)    {
  239.                     if(setcall(digis[i],argv[i+3]) == -1)    {
  240.                         sprintf(here->Error, "%sBad digipeater call %s",SCONFail, argv[i+3]);
  241.                         return -1;
  242.                     }
  243.                 }
  244.                 if(ax_add(target,AX_AUTO,digis,ndigis,ifp) == NULLAXR)    {
  245.                     sprintf(here->Error, "%sAX25 route add failed", SCONFail);
  246.                     return -1;
  247.                 }
  248.             }
  249.  
  250.             sp.ax->sax_family = AF_AX25;
  251.             strncpy(sp.ax->iface,argv[1],ILEN); /* the interface name */
  252.             setcall(sp.ax->ax25_addr,argv[2]); /* the remote callsign */
  253.             if((here->user = socket(AF_AX25,SOCK_STREAM,0)) == -1)    {
  254.                 sprintf (here->Error, "%sError allocating socket", SCONFail);
  255.                 return -1;
  256.             }
  257.             len = sizeof(*sp.ax);
  258.             break;
  259. #endif
  260.         default:
  261.             sp.in->sin_family = AF_INET;
  262.             if((sp.in->sin_addr.s_addr = resolve(argv[1])) == 0)    {
  263.                 sprintf (here->Error, "%sHost Unknown", SCONFail);
  264.                 return -1;
  265.             }
  266.             /* get the optional port number */
  267.             if(argc > 2)
  268.                 sp.in->sin_port = atoip(argv[2]);
  269.             else
  270.                 sp.in->sin_port = IPPORT_TELNET;
  271.             if((here->user = socket(AF_INET,SOCK_STREAM,0)) == -1)    {
  272.                 sprintf (here->Error, "%sError allocating socket", SCONFail);
  273.                 return -1;
  274.             }
  275.             len = sizeof(*sp.in);
  276.     }
  277.  
  278.     sockmode(here->user,SOCK_ASCII);
  279.     if(connect(here->user,sp.p,len) == -1) {
  280.         sprintf (here->Error, "SCRIPT connect failed: %s errno %d",
  281.                 sockerr(here->user),errno);
  282.         close_s(here->user);
  283.         return -1;
  284.     }
  285.     return here->user;
  286. }
  287.  
  288.  
  289. static struct cmds sconcmds[] = {
  290.     "tcp",        scriptconn,    0, 0, NULLCHAR,
  291.     "telnet",    scriptconn,    0, 0, NULLCHAR,
  292. #ifdef AX25
  293.     "ax25",        scriptconn,    0, 0, NULLCHAR,
  294.     "connect",    scriptconn,    0, 0, NULLCHAR,
  295. #endif
  296.     NULLCHAR
  297. };
  298.  
  299.  
  300.  
  301. static char *
  302. getnext (cp, put, here)
  303. char *cp, **put;
  304. struct world *here;
  305. {
  306. char *retval = cp, buf[4], c;
  307. time_t tm;
  308.  
  309.     buf[1] = 0;
  310.     if (*cp != '~')        {
  311.         buf[0] = *cp;
  312.         *put = strdup (buf);
  313.     } else    {
  314.         cp++;
  315.         retval++;
  316.         c = tolower (*cp);
  317.         time (&tm);
  318.         cp = ctime (&tm);
  319.         rip (cp);
  320.         cp[10] = cp[19] = 0;
  321.         switch (c)    {
  322.             case 'c':    *put = strdup (here->call);
  323.                     break;
  324.             case 'e':    *put = strdup (here->Error);
  325.                     break;
  326.             case '~':    
  327.             case 'b':    buf[0] = (c == 'b') ? '\007' : *retval;
  328.                     *put = strdup (buf);
  329.                     break;
  330.             case 'h':    *put = strdup (Hostname);
  331.                     break;
  332.             case 'd':    strcat (cp, ", ");
  333.                     strcat (cp, &cp[20]);
  334.                     *put = strdup (cp);
  335.                     break;
  336.             case 't':    *put = strdup (&cp[11]);
  337.                     break;
  338.             case 'n':    buf[0] = '\n';
  339.                     *put = strdup (buf);
  340.                     break;
  341.             case 'u':    /* un-terminate this line */
  342.                     rip (retval);
  343.                     buf[0] = *(++retval);
  344.                     *put = strdup (buf);
  345.                     break;
  346.             case '0':
  347.             case '1':
  348.             case '2':
  349.             case '3':
  350.             case '4':
  351.             case '5':
  352.             case '6':
  353.             case '7':
  354.             case '8':
  355.             case '9':    *put = strdup (here->variables[c - '0']);
  356.                     break;
  357.             case 'i':    if (retval[1] >= '0' &&  retval[1] <= '9')    {
  358.                         *put = malloc (20);
  359.                         sprintf (*put, "%-d", here->indexes[*(++retval) - '0']);
  360.                         break;
  361.                     }
  362.                     /* else fall through */
  363.             default:    sprintf (buf, "~%c", *retval);
  364.                     *put = strdup (buf);
  365.                     break;
  366.         }
  367.     }
  368.     return (retval);
  369. }
  370.  
  371.  
  372. static void
  373. process (here)
  374. struct world *here;
  375. {
  376. FILE *out = NULLFILE, *fp;
  377. int done = 0, skipping = 0, i, j, k, l, disconexit = 1;
  378. char buf[256], c, *cp, lastresponse = 'y', *label = 0;
  379. char *put;
  380. long pos;
  381.  
  382.     for (k = 0; k < 10; k++)    {
  383.         here->variables[k] = 0;
  384.         here->indexes[k] = 1;
  385.         here->socket[k] = 0;
  386.     }
  387.     here->user = here->socket[0] = Curproc->output;
  388.     if (here->user)        {    /* inherited a socket from a parent script! */
  389.         Curproc->output = here->socket[1] = here->user;
  390.         here->whichsocket = 1;
  391.         disconexit = 0;
  392.     }
  393.  
  394.     while (!done && fgets (buf, 256, here->fp))    {
  395. #ifdef MBXTDISC
  396.         /* Restart the inactivity timer */
  397.         if (here->m != NULLMBX)
  398.             start_timer(&here->m->tdisc);
  399. #endif
  400.         pwait (NULL);
  401.         if (buf[0] != '~' || buf[1] == '~')    {
  402.             if (!skipping)    {
  403.                 cp = buf;
  404.                 while (*cp)    {
  405.                     cp = getnext (cp, &put, here);
  406.                     mytprintf (here, put);
  407.                     free (put);
  408.                     cp++;
  409.                 }
  410.             }
  411.             continue;
  412.         }
  413.         c = tolower (buf[1]);
  414.         cp = skipwhite (&buf[2]);
  415.         rip (cp);
  416.         if (skipping && c != 'l')
  417.             continue;
  418.         k = *cp - '0';
  419.         switch (c)    {
  420.             case 'i':    /* modify an index counter
  421.                        index array in k, already */
  422.                     cp++;
  423.                     rip (cp);
  424.                     cp = skipwhite (cp);
  425.                     c = *cp++;
  426.                     cp = skipwhite (cp);
  427.                     l = getnum (cp, 1, here);
  428.                     switch (c)    {
  429.                         case '=':    /* assign */
  430.                                 here->indexes[k] = l;
  431.                                 break;
  432.                         case '+':    /* add */
  433.                                 here->indexes[k] += l;
  434.                                 break;
  435.                         case '-':    /* subtract */
  436.                                 here->indexes[k] -= l;
  437.                                 break;
  438.                         case '?':    /* compare */
  439.                                 c = lastresponse = (here->indexes[k] == l) ? 'y' : 'n';
  440.                                 cp = skipnonwhite (cp);
  441.                                 cp = skipwhite (cp);
  442.                                 if (*cp && c == 'y')
  443.                                     goto another;
  444.                                 break;
  445.                     }
  446.                     break;
  447. another:        case 'y':    /* on yes, goto label */
  448.             case 'n':    /* on no, goto label */
  449.                     if (lastresponse != c)
  450.                         break;
  451.             case 'g':    /* goto label */
  452.                     skipping = 1;
  453.                     free (label);
  454.                     label = strdup (cp);
  455.                     rewind (here->fp);
  456.                     break;
  457.             case 'l':    /* label line */
  458.                     if (skipping && !stricmp (cp, label))    {
  459.                         free (label);
  460.                         label = 0;
  461.                         skipping = 0;
  462.                     }
  463.                     break;
  464.             case 'b':    /* output 'n' blank lines */
  465.                     k = getnum (cp, 0, here);
  466.                     if (!k)
  467.                         k = 1;
  468.                     while (k--)
  469.                         mytprintf (here, "\n");
  470.                     break;
  471.             case 'm':    /* more prompt */
  472.                     mytprintf (here, "\n---MORE (*y/n)---\n");
  473.                     mygets (buf, 256, here);
  474.                     pwait (NULL);
  475.                     if (tolower (buf[0]) != 'n')
  476.                         break;
  477.             case 'x':    /* exit at this point */
  478. /*                    done = 1;    */
  479.                     skipping = 1;
  480.                     free (label);
  481.                     label = strdup ("exit");
  482.                     break;
  483.             case 'q':    /* query with string for y/n answer */
  484.                     mytprintf (here, cp);
  485.                     mytprintf (here, " (*y/n)\n");
  486.                     mygets (buf, 256, here);
  487.                     pwait (NULL);
  488.                     lastresponse = (tolower (buf[0]) == 'n') ? 'n' : 'y';
  489.                     break;
  490.             case 'j':    /* just compare first characters */
  491.             case 'c':    /* compare entire strings
  492.                        first string value in k, already */
  493.                     cp = nextarg (cp, &l);
  494.                     if (!here->variables[l] || !here->variables[k])
  495.                         lastresponse = 'n';
  496.                     else    {
  497.                         if (c == 'c')
  498.                             c = lastresponse = (stricmp (here->variables[l], here->variables[k])) ? 'n' : 'y';
  499.                         else    {
  500.                             cp = nextnum (cp, 0, here, &j);
  501.                             c = lastresponse = (strnicmp (here->variables[l], here->variables[k], j)) ? 'n' : 'y';
  502.                         }
  503.                         cp = skipnonwhite (cp);
  504.                         cp = skipwhite (cp);
  505.                         if (*cp && c == 'y')
  506.                             goto another;
  507.                     }
  508.                     break;
  509.             case 'h':    /* string has substring?
  510.                        first string value in k, already */
  511.                     cp = nextarg (cp, &l);
  512.                     if (!here->variables[l] || !here->variables[k])
  513.                         lastresponse = 'n';
  514.                     else    {
  515.                         i = (int) strstr (here->variables[k], here->variables[l]);
  516.                         c = lastresponse = (!i) ? 'n' : 'y';
  517.                         if (i)
  518.                             i -= (int) here->variables[k];
  519.                         cp = nextarg (cp, &j);
  520.                         here->indexes[j] = i;
  521.                         cp = skipnonwhite (cp);
  522.                         cp = skipwhite (cp);
  523.                         if (*cp && c == 'y')
  524.                             goto another;
  525.                     }
  526.                     break;
  527.             case 'p':    /* pick out a sub-string
  528.                        to variable already in k */
  529.                     cp = nextarg (cp, &j);        /* from variable */
  530.                     cp = nextnum (cp, 0, here, &i);    /* start index */
  531.                     cp = nextnum (cp, 0, here, &l);    /* length */
  532.                     if ((strlen(here->variables[j]) - i) < l)
  533.                         l = strlen (here->variables[j]) - i;
  534.                     l++;    /* allow room for zero byte */
  535.                     free (here->variables[k]);
  536.                     here->variables[k] = malloc (l);
  537.                     strncpy (here->variables[k], &here->variables[j][i], l);
  538.                     here->variables[k][l - 1] = 0;
  539.                     break;
  540.             case 't':    /* truncate a variable string */
  541.                     cp = nextarg (cp, &j);
  542.                     if (strlen (here->variables[k]) > j)
  543.                         here->variables[k][j] = 0;
  544.                     break;
  545.             case 'z':    /* get length of variable and place in index */
  546.                     cp = nextarg (cp, &j);
  547.                     here->indexes[j] = (here->variables[k]) ? strlen (here->variables[k]) : 0;
  548.                     break;
  549.             case 'a':    /* assign a string to a variable */
  550.             case 'v':    /* prompt and place result in variable */
  551.                     free (here->variables[k]);
  552.                     cp++;
  553.                     cp = skipwhite (cp);
  554.                     if (c == 'a')    {
  555.                         if (*cp == '~')
  556.                             getnext (cp, &here->variables[k], here);
  557.                         else
  558.                             here->variables[k] = strdup(cp);
  559.                     } else    {
  560.                         if (cp)    {
  561.                             mytprintf (here, cp);
  562.                             mytprintf (here, "\n");
  563.                         }
  564.                         mygets (buf, 256, here);
  565.                         pwait (NULL);
  566.                         here->variables[k] = strdup (buf);
  567.                     }
  568.                     break;
  569.             case 'd':    /* deliver a mail file */
  570.                     getnext(cp, &put, here);    /* allow ~c and ~# subs */
  571.                     if (strlen (put) == 1)    {
  572.                         char *cp2;
  573.                         free (put);
  574.                         put = strdup (cp);
  575.                         cp2 = strchr (put, ' ');
  576.                         *cp2 = 0;
  577.                     }
  578.                     lastresponse = 'n';    /* default to fails */
  579.                     /* get filename and open it */
  580.                     cp = strchr (cp, ' ');
  581.                     if (cp)        {    /* if filename given */
  582.                         FILE *out2;
  583.                         *cp++ = 0;
  584.                         out2 = NULLFILE;
  585.                         if (stricmp (cp, "null"))
  586.                             out2 = fopen (cp, READ_TEXT);
  587.                         /* save current pos, and get tutor description */
  588.                         pos = ftell(here->fp);
  589.                         rewind (here->fp);
  590.                         fgets (buf, 256, here->fp);
  591.                         fseek (here->fp, pos, SEEK_SET);
  592.                         cp = skipwhite (buf);
  593.                         rip (cp);
  594.                         /* now mail the file */
  595.                         rdaemon (out2, NULLCHAR, put, cp, 'P', 0);
  596.                         lastresponse = 'y';
  597.                         if (out2 != NULLFILE)
  598.                             fclose (out2);
  599.                     }
  600.                     free (put);
  601.                     break;
  602.                         
  603.             case 'e':    /* is io file at end of file */
  604.                     if (out != NULLFILE)    {
  605.                         c = lastresponse = (feof (out)) ? 'y' : 'n';
  606.                         if (*cp && c == 'y')
  607.                             goto another;
  608.                     }
  609.                     break;
  610.             case 's':    /* seek to start of io file */
  611.                     if (out != NULLFILE)    {
  612.                         if (tolower (*cp) == 'e')
  613.                             fseek (out, 0L, 2);
  614.                         else
  615.                             rewind (out);
  616.                     }
  617.                     break;
  618.             case 'u':    /* upload a text file */
  619.                     if ((fp = fopen (cp, READ_TEXT)) != NULLFILE)    {
  620. #ifndef STANDALONE
  621.                         sendfile (fp, Curproc->output, ASCII_TYPE, 0);
  622. #else
  623.                         sendfile (fp);
  624. #endif
  625.                         fclose (fp);
  626.                     }
  627.                     break;
  628.             case 'o':    /* open an old io file */
  629.             case 'f':    /* create a new io file */
  630.                     if (out != NULLFILE)
  631.                         fclose (out);
  632.                     out = NULLFILE;
  633.                     out = fopen (cp, (c == 'f') ? CREATE_TEXT : UPDATE_TEXT);
  634.                     lastresponse = (out == NULLFILE) ? 'n' : 'y';
  635.                     break;
  636.             case 'w':    /* write a textline to the io file */
  637.                     if (out != NULLFILE)
  638.                         while (*cp)    {
  639.                             cp = getnext (cp, &put, here);
  640.                             fprintf (out, put);
  641.                             free (put);
  642.                             cp++;
  643.                         }
  644.                     break;
  645.             case 'r':    /* read a line from io file in var */
  646.                     if (out != NULLFILE)    {
  647.                         free (here->variables[k]);
  648.                         fgets (buf, 256, out);
  649.                         rip (buf);
  650.                         here->variables[k] = strdup(buf);
  651.                     }
  652.                     break;
  653.             case 'k':    /* kill a file */
  654.                     unlink (cp);
  655.                     lastresponse = (access (cp, 0)) ? 'y' : 'n';
  656.                     break;
  657.             case '?':    switch (tolower (*cp))    {
  658.                         case 'c':    lastresponse = (!here->color) ? 'n' : 'y';
  659.                                 break;
  660.                         case 'i':    lastresponse = (here->ipconnect) ? 'y' : 'n';
  661.                                 break;
  662.                     }
  663.                     break;
  664.             case '!':    switch (tolower (*cp))    {
  665.                         case 'c':    here->color = 1;
  666.                                 break;
  667.                     }
  668.                     break;
  669.             case '*':    switch (tolower (*cp))    {
  670.                         case 'b':    here->colorblock = 1;
  671.                                 break;
  672.                         case 'e':    here->colorblock = 0;
  673.                                 break;
  674.                     }
  675.                     break;
  676.             case '%':    lastresponse = (!here->color) ? 'n' : 'y';
  677.                     if (here->color)
  678.                         colorfile (cp, here->last);
  679.                     break;
  680.             case '@':    mycolorchange (here, cp, here->last);
  681.                     break;
  682.             case '$':    {
  683.                     char *args[2];
  684.  
  685.                         args[1] = cp;
  686.                         if(access(cp,4))
  687.                             lastresponse = 'n';
  688.                         else    {
  689.                             Curproc->output = here->socket[0];
  690.                             doscript (0, args, here->user);
  691.                             lastresponse = 'y';
  692.                             Curproc->output = here->user;
  693.                         }
  694.                     }
  695.                     break;
  696.             case ')':    lastresponse = 'n';
  697.                     if (!k)
  698.                         sprintf (here->Error, "%scan't close stream 0", SCONFail2);
  699.                     else if (here->socket[k] <= 0)
  700.                         sprintf (here->Error, "%sstream %d not connected", SCONFail2, k);
  701.                     else    {
  702.                         lastresponse = 'y';
  703.                         here->Error[0] = 0;
  704.                         if(socklen(here->socket[k],0)) /* discard any remaining input */
  705.                             recv_mbuf(here->socket[k],NULL,0,NULLCHAR,0);
  706.                         shutdown(here->socket[k],1);
  707.                         close_s (here->socket[k]);
  708.                         if (Curproc->output == here->socket[k])    {
  709.                             Curproc->output = here->socket[0];
  710.                              here->user = here->whichsocket = 0;
  711.                         }
  712.                         here->socket[k] = 0;
  713.                     }
  714.                     break;
  715.             case '#':    lastresponse = 'n';
  716.                     if (k && here->socket[k] < 0)
  717.                         sprintf (here->Error, "%sstream %d not connected", SCONFail, k);
  718.                     else    {
  719.                         lastresponse = 'y';
  720.                          Curproc->output = here->socket[k];
  721.                          here->user = (k) ? here->socket[k] : 0;
  722.                          here->whichsocket = k;
  723.                     }
  724.                     break;
  725.             case '(':    lastresponse = 'n';
  726.                     if (here->socket[k])
  727.                         sprintf (here->Error, "%sstream %d already connected", SCONFail2, k);
  728.                     else    {
  729.                         cp = skipnonwhite(cp);
  730.                         cp = skipwhite (cp);
  731.                         if ((here->socket[k] = cmdparse(sconcmds,cp,(void *)here)) != -1)
  732.                             lastresponse = 'y';
  733.                         else
  734.                             here->socket[k] = 0;
  735.                     }
  736.                     break;
  737.             case '=':    lastresponse = (here->socket[k] > 0) ? 'y' : 'n';
  738.                     break;
  739.             default:    break;
  740.         }
  741.     }
  742.     if (out != NULLFILE)
  743.         fclose (out);
  744.     free (label);
  745.     Curproc->output = here->socket[0];
  746.     for (k = 0; k < 10; k++)    {
  747.         free (here->variables[k]);
  748.         if (disconexit && k && here->socket[k] > 0)    {    /* free connected streams */
  749.             if(socklen(here->socket[k],0)) /* discard any remaining input */
  750.                 recv_mbuf(here->socket[k],NULL,0,NULLCHAR,0);
  751.             shutdown(here->socket[k],1);
  752.             close_s (here->socket[k]);
  753.         }
  754.     }
  755.     here->user = 0;    
  756.     here->whichsocket = 0;
  757. }
  758.  
  759.  
  760. static char *tutorialName[] = {"Learning Center", "Information Center", "News Center"};
  761. static char banner[] = "For %s, connect to '%s' using the same path...\n";
  762.  
  763. static void
  764. buildmenu (here)
  765. struct world *here;
  766. {
  767. FILE *fp;
  768. char buf[80], buf2[256], *cp;
  769. struct ffblk ff;
  770.  
  771.     here->maxselect = 0;
  772.     if (here->subdir)
  773.         tprintf ("Current Sub-directory: %s\n\n", here->subdir);
  774.     mycolorchange (here, "0F", here->last);
  775.     tprintf ("\nWelcome to the ");
  776.     mycolorchange (here, "0C", here->last);
  777.     tprintf ("TNOS %s ",tutorialName[here->mode]);
  778.     mycolorchange (here, "0F", here->last);
  779.     tprintf ("at ");
  780.     mycolorchange (here, "05", here->last);
  781.     tprintf ("%s\n\n     %c", Hostname,here->subdir ? 'E' : '0');
  782.     mycolorchange (here, "07", here->last);
  783.     tprintf (" -  Exit %s\n", tutorialName[here->mode]);
  784.     mycolorchange (here, "05", here->last);
  785.     tprintf ("     %c", (here->subdir) ? '0' : 'C');
  786.     mycolorchange (here, "07", here->last);
  787.     if (here->subdir)
  788.         tputs (" -  Return to Previous Menu\n");
  789.     else
  790.         tprintf (" -  %sable ANSI Color Graphics\n", (here->color) ? "Dis" : "En");
  791.     sprintf(buf,"%s/%s*.tut",(here->mode == 1) ? Info : (here->mode) ? News : Tutor, (here->subdir) ? here->subdir : "");
  792.     if (findfirst(buf, &ff, 0) == 0)     {
  793.         do    {
  794.             pwait(NULL);    /* Let others run */
  795.             *(strchr(ff.ff_name,'.')) = '\0';
  796.             sprintf (buf2, "%s/%s%s.tut", (here->mode == 1) ? Info : (here->mode) ? News : Tutor, (here->subdir) ? here->subdir : "", ff.ff_name);
  797.             if ((fp = fopen (buf2,READ_TEXT)) != NULLFILE)    {
  798.                 do    {
  799.                     fgets (buf2, 256, fp);
  800.                     cp = skipwhite (buf2);
  801.                 } while (*cp == '\n');
  802.                 fclose (fp);
  803.                 if (*cp == '~')        /* subdir directing file */
  804.                     cp = skipwhite(skipnonwhite(skipwhite (++cp)));
  805.                 here->Tutors[here->maxselect++] = strdup (ff.ff_name);
  806.                 mycolorchange (here, "05", here->last);
  807.                 tprintf ("    %2d", here->maxselect, cp);
  808.                 mycolorchange (here, "07", here->last);
  809.                 tprintf (" -  %s", cp);
  810.                 }
  811.             } while (findnext(&ff) == 0);
  812.     }
  813. }
  814.  
  815.  
  816. void
  817. #ifndef STANDALONE
  818. tutorserv (call, m, mode, color, ip)
  819. char *call;
  820. struct mbx *m;
  821. int mode, color, ip;
  822. #else
  823. tutorserv (call, mode, color, ip)
  824. char *call;
  825. int mode, color, ip;
  826. #endif
  827. {
  828. char selection[10], filename[80], *cp;
  829. int k, select, inited = 0;
  830. struct world here;
  831. #ifndef STANDALONE
  832. char tmp[AXBUF];
  833.  
  834.     Tutored++;
  835. #endif
  836.     here.mode = mode;
  837. #ifndef STANDALONE
  838.     Tutorlogins[here.mode]++;
  839. #endif
  840.     here.maxselect = 0;
  841.     here.call = call;
  842. #ifndef STANDALONE
  843.     here.m = m;
  844. #endif
  845.     here.subdir = NULLCHAR;
  846. #ifndef STANDALONE
  847.     sockblock(Curproc->output,SOCK_NOTXBLOCK);   /* prevent backlogs ! */
  848. #endif
  849.     here.color = color;
  850.     here.ipconnect = ip;
  851.     here.inescape = 0;
  852.     here.Error[0] = 0;
  853.     here.whichsocket = here.background = 0;
  854.     here.user = here.socket[0] = Curproc->output;
  855.     if (m && color)
  856.         memcpy (here.last, m->colorset, 2);
  857.     else
  858.         here.last[0] = 0;
  859.     for ( ; ; )    {
  860.         if (inited)
  861.             tprintf ("\n\n\n\n");
  862.         else
  863.             inited = 1;
  864.         buildmenu (&here);
  865.         do    {
  866.             mycolorchange (&here, "0F", here.last);
  867.             tprintf ("\nEnter Selection:\n");
  868.             mygets (selection, 10, &here);
  869.             pwait (NULL);
  870.             if (toupper (*selection) == 'E')    {
  871.                 free (here.subdir);
  872.                 here.subdir = NULLCHAR;
  873.                 select = 0;
  874.                 break;
  875.             }
  876.             if (toupper (*selection) == 'C')    {
  877.                 select = -1;
  878.                 here.color ^= 1;
  879.                 break;
  880.             }
  881.             select = atoi (selection);
  882.             if (!select)
  883.                 break;
  884.             if (select > here.maxselect)
  885.                 tprintf ("Invalid number... select 0 - %-d!\007\n", here.maxselect);
  886.         } while (select > here.maxselect);
  887.         if (select == -1)
  888.             continue;
  889.         if (select)
  890.             sprintf (filename, "%s/%s%s.tut", (here.mode == 1) ? Info : (here.mode) ? News : Tutor, (here.subdir) ? here.subdir : "", here.Tutors[select - 1]);
  891.         for (k = 0; k < here.maxselect; k++)
  892.             free (here.Tutors[k]);
  893.         if (!select)    {
  894.             if (!here.subdir)    /* not in a sub-directory! */
  895.                 break;
  896.             here.subdir[strlen(here.subdir) - 1] = 0; /* take off last "/" */
  897.             cp = strrchr (here.subdir, '/');
  898.             if (!cp)    {
  899.                 free (here.subdir);
  900.                 here.subdir = NULLCHAR;
  901.             } else
  902.                 *(++cp) = 0;
  903.             continue;
  904.         }
  905.         if ((here.fp = fopen (filename,READ_TEXT)) == NULLFILE)    {
  906.             tprintf ("Sorry, but something seems to be wrong with that tutorial!\n");
  907.             continue;
  908.         }
  909.         /* Let's check first line to see if this file describes a sub-directory */
  910.         fgets (filename, 80, here.fp);
  911.         cp = filename;
  912.         if (*cp == '~')        {    /* Yep! Sub-directory time! */
  913.             cp = skipwhite (++cp);
  914.             for (k = 0; k < 8 && *cp && cp[k] != '\t' && cp[k] != ' '; k++)
  915.                 selection[k] = cp[k];
  916.             selection[k++] = '/';
  917.             selection[k] = 0;
  918.             k += (here.subdir) ? strlen(here.subdir) : 0;
  919.             cp = malloc (++k);
  920.             *cp = 0;
  921.             if (here.subdir)
  922.                 strcpy (cp, here.subdir);
  923.             strcat (cp, selection);
  924.             free (here.subdir);
  925.             here.subdir = cp;
  926.         } else    {
  927.             rewind (here.fp);
  928.             process (&here);
  929.         }
  930.         fclose (here.fp);
  931.     }
  932.     mycolorchange (&here, "09", here.last);
  933.     tprintf ("\n\nThanks for using the ");
  934.     mycolorchange (&here, "0C", here.last);
  935.     tprintf ("TNOS %s ", tutorialName[here.mode]);
  936.     mycolorchange (&here, "09", here.last);
  937.     tprintf ("at ");
  938.     mycolorchange (&here, "0E", here.last);
  939.     tprintf ("%s\n\n", Hostname);
  940.     mycolorchange (&here, "0F", here.last);
  941.     if (m)
  942.         mycolorchange (&here, m->colorset, here.last);
  943. #ifndef STANDALONE
  944.     pax25(tmp, Tcall);
  945.     if (*tmp && mode && Stutor != -1)    /* if tutor server active, but not 'us */
  946.         tprintf (banner,"tutorial assistance", tmp);
  947.     pax25(tmp, Icall);
  948.     if (*tmp && mode != 1 && Sinfo != -1)    /* if info server active, but not 'us' */
  949.         tprintf (banner,"local/area information", tmp);
  950.     pax25 (tmp, Ncall);
  951.      if (*tmp && mode != 2 && Snews != -1)    /* if news server active, but not 'us' */
  952.         tprintf (banner, "Ham related NEWS", tmp);
  953.     tputc ('\n');
  954.     usflush(Curproc->output);
  955.     sockblock(Curproc->output,SOCK_BLOCK);
  956.     Tutored--;
  957. #endif
  958. }
  959.  
  960.  
  961. extern char NoRead[];
  962. static short scriptmode = 0;
  963.  
  964.  
  965. int
  966. scriptcmd(inherited,fp,name)
  967. int inherited;    /* non-zero, inherited socket # */
  968. FILE *fp;
  969. char *name;
  970. {
  971. struct session *sp;
  972. int usesession = 0;
  973. struct world here;
  974.  
  975.     /* Use a session if this comes from console - WG7J*/
  976.     if(!scriptmode && Curproc->input == Command->input) {
  977.         usesession = 1;
  978.         if((sp = newsession(name,SCRIPT,0)) == NULLSESSION)
  979.             return 1;
  980.     }
  981.  
  982.     here.fp = fp;
  983.     here.mode = 0;
  984.     here.maxselect = 0;
  985.     here.call = "NoName";
  986.     here.m = NULLMBX;
  987.     here.subdir = NULLCHAR;
  988.     here.color = 0;
  989.     here.ipconnect = 1;
  990.     here.inescape = 0;
  991.     here.last[0] = 0;
  992.     here.Error[0] = 0;
  993.     here.whichsocket = 0;
  994.     here.user = inherited;
  995.     here.background = scriptmode;
  996.     process (&here);
  997.     fclose(here.fp);
  998.  
  999.     if(usesession) {
  1000.         keywait(NULLCHAR,1);
  1001.         freesession(sp);
  1002.     }
  1003.     return 0;
  1004. }
  1005.         
  1006.  
  1007. int
  1008. doscript(argc,argv,p)
  1009. int argc;
  1010. char *argv[];
  1011. void *p;
  1012. {
  1013. FILE *fp;
  1014. int oldin, oldout;
  1015.  
  1016.     {
  1017.     char fname[256];
  1018.         strcpy(fname,make_fname(Command->curdirs->dir,argv[1]));
  1019.         if((fp = fopen(fname,READ_TEXT)) == NULLFILE){
  1020.             tprintf(NoRead,fname,sys_errlist[errno]);
  1021.             return 1;
  1022.         }
  1023.     }
  1024.  
  1025.     scriptmode = (argc > 2 && !strnicmp (argv[2], "back", 4)) ? 1 : 0;
  1026.     oldin = Curproc->input;
  1027.     oldout = Curproc->output;
  1028.     if (scriptmode)    
  1029.         Curproc->input = Curproc->output = -1;
  1030.  
  1031.     if(scriptmode || Curproc->input == Command->input)
  1032.         newproc("script",2048,(void (*)())scriptcmd,(argc) ? 0 : (int) p,(void *)fp,(void *)strdup(argv[1]),2);
  1033.     else
  1034.         scriptcmd((argc) ? 0: (int) p,fp,argv[1]);
  1035.     if (scriptmode)    {
  1036.         Curproc->input = oldin;
  1037.         Curproc->output = oldout;
  1038.     }
  1039.     return 0;
  1040. }
  1041.  
  1042.  
  1043.  
  1044.  
  1045. #endif
  1046.  
  1047.